<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 *
 * @author Administrator
 *
 */
class My_ci_model extends CI_Model
{
    protected $primary_id = '';
    protected $primary_name = '';
    protected $table_prefix = 'mb_'; //表前缀
    protected $page_visible = TRUE;
    protected $result = array('error' => 0, 'message' => '', 'content' => '', 'data' => '');

    static $access_statement = NULL;

    protected $my_redis = null;
    protected $redis_config = 'eh_redis';

    /**
     * 逻辑删除数据
     * @param $primary_id
     * @param $datas
     */
    public function logically_delete($primary_id, $datas)
    {
        $db_data = $this->check_post_form_datas($datas);
        $this->db->where($this->primary_id, $primary_id);
        $this->db->update($this->table, $db_data);
    }

    /**
     *
     * @access public
     *
     */
    function __construct($settings = array(), $sessions = array())
    {
        parent::__construct();
        $this->setting($settings, $sessions);
    }

    public function setting($settings = array(), $sessions = array())
    {
        if (!empty($settings)) {
            foreach ($settings as $key => $val) {
                $this->$key = $val;
            }
        }
        if (!empty($sessions)) {
            foreach ($sessions as $val) {
                $this->$val = $this->session->userdata($val);
            }
        }
    }

    /**
     * 获取表前缀
     *
     * @return table_prefix
     */
    public function get_table_prefix()
    {
        return $this->table_prefix;
    }

    public function kick_out_admin($admin_id)
    {
        $this->db->select('last_session');
        $this->db->from('helper');
        $this->db->where('id', $admin_id);
        $info = $this->db->get()->row_array();
        if (isset($info['last_session'])) {
            $this->session_delete($info['last_session']);
        }
    }

    public function session_delete($id)
    {
        $this->db->where('id', $id);
        $this->db->delete('session_mer');
    }

    /**
     * 取出详情
     * @param unknown $primary_id
     * @return unknown
     */
    public function get_info($primary_id, $fields = '*')
    {
        if ($primary_id > 0) {
            $this->db->select($fields);
            $this->db->from($this->table);
            $this->db->where($this->primary_id, $primary_id);
            $info = $this->db->get()->row_array();
        } else {
            $info                      = array();
            $info[$this->primary_id]   = $primary_id;
            $info[$this->primary_name] = '';
        }
        return $this->process_info($info);
        //return $info;
    }


    /**
     * 处理输出字段
     * @param array $info
     */
    public function process_info($info = array())
    {
        return $info;
    }

    /**
     * 获取分页数据
     * @param array $filter
     * @param number $page
     * @param number $page_size
     * @return multitype:Ambigous <multitype:, number> multitype:string
     */
    public function get_list($filter = array(), $page = 1, $page_size = 15)
    {
        $list = array();
        //初始化条件
        if (isset($filter['sort']) && !empty($filter['sort'])) {
            $filter['sort'] = trim($filter['sort']);
            if (!$this->check_single_field($filter['sort'])) {
                $filter['sort'] = $this->primary_id;
            }
        } else {
            $filter['sort'] = $this->primary_id;
        }
        $filter['order'] = isset($filter['order']) && !empty($filter['order']) ? trim($filter['order']) : 'desc';
        //获取记录数
        $record_count = $this->get_list_count($filter);//print($record_count);die();

        $pager = $this->page_and_size($filter, $record_count, $page, $page_size);

        if ($pager['record_count'] > 0) {
            $item_list = $this->query_item_list($filter, $pager);

            $list = $this->reformat_list_datas($item_list);
        }
        return array('list' => $list, 'pager' => $pager);
    }

    /**
     * 列表查询条件
     * @param unknown $filter
     * @param unknown $pager
     */
    public function query_item_list($filter, $pager)
    {
        $this->db->select('a.*');
        $this->db->from($this->table . ' as a');

        $this->list_query_filter($filter);

        //列表排序条件
        $this->query_list_sort_order($filter);

        $this->db->limit($pager['page_size'], $pager['start']);
        $item_list = $this->db->get()->result_array();
// 		print($this->db->last_query());
// 		die();
        return $item_list;
    }

    /**
     * 列表排序条件
     * @param unknown $filter
     * @param unknown $pager
     */
    public function query_list_sort_order($filter)
    {
        $this->db->order_by($filter['sort'], $filter['order']);
    }

    /**
     * 统计数量
     * @param array $filter
     * @return number
     */
    public function get_list_count($filter = array())
    {
        $this->db->from($this->table . ' as a');
        $this->list_query_filter($filter);
        return (int)$this->db->count_all_results();
    }

    /**
     * 查询条件
     * @param array $filter
     * @return void
     */
    public function list_query_filter($filter = array())
    {
        if (isset($filter['keywords']) && !empty($filter['keywords'])) {
            $whereKW = '(a.' . $this->primary_name . ' like "%' . $filter['keywords'] . '%" ' .
                'or a.' . $this->primary_id . ' like "%' . $filter['keywords'] . '%")';
            $this->db->where($whereKW);
        }
    }

    /**
     * 新增数据(多条)
     * @param unknown $datas
     */
    public function add_datas($datas)
    {
        $keys    = array();
        $db_vals = array();
        foreach ($datas as $item) {
            if (empty($keys)) {
                foreach ($item as $k => $val) {
                    $keys[] = $k;
                }
            }
            $db_val = array();
            foreach ($item as $k => $val) {
                $db_val[] = "'" . $val . "'";
            }
            $db_vals[] = $db_val;
        }
        $sqldb = 'insert INTO  ' . $this->table_prefix . $this->table . ' (' . implode(',', $keys) . ') VALUES';
        $sql   = array();
        foreach ($db_vals as $it) {
            $sql[] = "( " . implode(',', $it) . " )";
        }
        if ($this->db->query($sqldb . implode(',', $sql))) {
            $this->result[$this->primary_id] = 0;
        } else {
            $this->result['error']   = 1;
            $this->result['message'] = '写入多条数据出错';
        }

        return $this->result;
    }

    /**
     * 新增数据集合
     * @param unknown $datas
     */
    public function add_data($datas)
    {
        $db_data = $this->check_post_form_datas($datas);

        if (!empty($db_data)) {
            $this->db->insert($this->table, $db_data);
            $this->result[$this->primary_id] = $this->db->insert_id();
        } else {
            $this->result['error']   = 1;
            $this->result['message'] = '未写入任何数据';
        }
        return $this->result;
    }

    /**
     * 修改数据
     * @param unknown $datas
     * @param unknown $primary_id
     * @return multitype:number string
     */
    public function edit_data($datas, $primary_id, $where_in = FALSE)
    {
        try {
            $db_data = $this->check_post_form_datas($datas);
            if (!empty($db_data)) {
                if ($where_in) {
                    $this->db->where_in($this->primary_id, $primary_id);
                } else {
                    $this->db->where($this->primary_id, $primary_id);
                }
                $this->db->update($this->table, $db_data);
                $this->result[$this->primary_id] = $primary_id;
            } else {
                $this->result['error']   = 1;
                $this->result['message'] = '未更新任何数据';
            }
        } catch (Exception $e) {
            $this->result['error']   = 1;
            $this->result['message'] = $e->getMessage();
        }
        return $this->result;
    }

    /**
     * 删除数据
     * @param unknown $primary_id
     * @return multitype:number string
     */
    public function delete_data($primary_id)
    {
        try {
            if (is_array($primary_id)) {
                $this->db->where_in($this->primary_id, $primary_id);
            } else {
                $this->db->where($this->primary_id, $primary_id);
            }
            $this->db->delete($this->table);
            $this->result[$this->primary_id] = $primary_id;
        } catch (Exception $e) {
            $this->result['error']   = 1;
            $this->result['message'] = $e->getMessage();
        }
        return $this->result;
    }

    /**
     * 格式化输出字段
     * @param unknown $item_list
     * @return multitype:unknown
     */
    function reformat_list_datas($item_list)
    {
        /* $arr = array();
        foreach ($item_list as $row) {
            $arr[] = $row;
        }
        return $arr; */
        return $item_list;
    }

    /**
     * 检查字段的合法性，过滤非法字段
     * @param unknown $datas
     * @return unknown
     */
    public function check_post_form_datas($datas)
    {
        if (self::$access_statement == NULL) {
            self::$access_statement = $this->db->list_fields($this->table);
        }
        $access_statement = self::$access_statement;
        $exclude_fields   = array($this->primary_id);
        if (!empty($exclude_fields)) {
            $access_statement = array_diff($access_statement, $exclude_fields);
        }
        foreach ($datas as $key => $val) {
            if (!in_array($key, $access_statement)) {
                unset($datas[$key]);
            }
            if (is_array($val)) {
                $datas[$key] = implode(',', $val);
            }
        }
        return $datas;
    }

    /**
     * 检查单个字段的合法性
     * @param unknown $datas
     * @return bool
     */
    public function check_single_field($field)
    {
        if (self::$access_statement == NULL) {
            self::$access_statement = $this->db->list_fields($this->table);
        }
        return in_array($field, self::$access_statement);
    }

    /**
     * 分页的信息加入条件的数组
     *
     * @access  public
     * @return  array
     */
    function page_and_size($filter = array(), $record_count = 0, $page = 1, $page_size = 15)
    {
        //$filter['router'] = $this->router->class;
        $filter['router'] = rtrim($this->router->directory, '/') . '/' . $this->router->class;
        /*$filter['uri'] = site_url($this->router->class);*/
        $filter['uri'] = site_url($this->uri->uri_string);
        //当访问的页面是首页是，uri中需要补全默认控制器，eg:home ($this->uri->rsegments[0])
        if ((isset($this->uri->rsegments[1]) && $this->uri->rsegments[1] == $this->router->default_controller) && (isset($this->uri->rsegments[2]) && $this->uri->rsegments[2] == 'index')) {
            $filter['uri'] .= '/home';
        }

        if (!isset($filter['page'])) {
            $filter['page'] = $page;
        }
        $pager['visible']      = $this->page_visible;
        $pager['filter']       = $filter;
        $pager['record_count'] = $record_count;

        $pager['page_size'] = $page_size;
        if (isset($filter['page_size']) && $filter['page_size'] > 0) {
            $pager['page_size'] = $filter['page_size'];
        }
        /* page 总数 */
        $page_count          = (!empty($pager['record_count']) && $pager['record_count'] > 0) ? ceil($pager['record_count'] / $pager['page_size']) : 1;
        $page_prev           = ($page > 1) ? $page - 1 : 1;
        $page_next           = ($page < $page_count) ? $page + 1 : $page_count;
        $pager['page_count'] = $page_count;
        $pager['page']       = $page > $pager['record_count'] ? $pager['record_count'] : $page;
        //记录起始
        $pager['start'] = ($pager['page'] - 1) * $pager['page_size'];

        $_pagenum = 10;     // 显示的页码
        $_offset  = 2;       // 当前页偏移值
        $_from    = $_to = 0;  // 开始页, 结束页
        if ($_pagenum > $page_count) {
            $_from = 1;
            $_to   = $page_count;
        } else {
            $_from = $page - $_offset;
            $_to   = $_from + $_pagenum - 1;
            if ($_from < 1) {
                $_to   = $page + 1 - $_from;
                $_from = 1;
                if ($_to - $_from < $_pagenum) {
                    $_to = $_pagenum;
                }
            } elseif ($_to > $page_count) {
                $_from = $page_count - $_pagenum + 1;
                $_to   = $page_count;
            }
        }
        $pager['page_first'] = $page > 1 ? 1 : '';//($page - $_offset > 1 && $_pagenum < $page_count) ? 1 : '';
        $pager['page_prev']  = ($page > 1) ? $page_prev : '';
        $pager['page_next']  = ($page < $page_count) ? $page_next : '';
        $pager['page_last']  = $page < $page_count ? $page_count : '';//($_to < $page_count) ? $page_count : '';
        for ($i = $_from; $i <= $_to; ++$i) {
            $pager['page_number'][$i] = $i;
        }
        return $pager;
    }

    /**
     * 统计回收站的数量
     * @param array $filter
     * @return number
     */
    public function get_trash_count()
    {
        if ($this->check_single_field('is_delete')) {
            $this->db->from($this->table . ' as a');
            $this->db->where('a.is_delete', 1);
            return (int)$this->db->count_all_results();
        } else {
            return 0;
        }
    }

    public function get_layer_list($filter = array())
    {
        $this->db->select('a.*, COUNT(b.' . $this->primary_id . ') AS has_children');
        $this->db->from($this->table . ' as a');
        $this->db->join($this->table . ' as b', 'a.' . $this->primary_id . ' = b.parent_id', 'left');

        $this->list_query_filter($filter);

        $this->db->group_by('a.' . $this->primary_id);
        $this->db->order_by('a.parent_id', 'asc');
        //	$this->db->order_by('a.sort_order', 'asc');
        $item_list = $this->db->get()->result_array();

        $list = $this->layer_list_options($item_list);

        $list = $this->reformat_list_datas($list);

        if (isset($filter['exclude_id']) && $filter['exclude_id'] > 0) {
            unset($list[$filter['exclude_id']]);
        }
        $record_count = count($list);

        $this->page_visible = FALSE;
        $pager              = $this->page_and_size($filter, $record_count);


        return array('list' => $list, 'pager' => $pager);
    }

    /**
     * 过滤和排序所有分类，返回一个带有缩进级别的数组
     *
     * @access  private
     * @param   int $cat_id 上级分类ID
     * @param   array $arr 含有所有分类的数组
     * @param   int $level 级别
     * @return  void
     */
    function layer_list_options($arr)
    {
        $level   = $last_cat_id = 0;
        $options = $cat_id_array = $level_array = array();

        while (!empty($arr)) {
            foreach ($arr AS $key => $value) {
                $cat_id = $value[$this->primary_id];
                if ($level == 0 && $last_cat_id == 0) {
                    if ($value['parent_id'] > 0) {
                        break;
                    }
                    $options[$cat_id]             = $value;
                    $options[$cat_id]['level']    = $level;
                    $options[$cat_id]['opt_name'] = str_repeat('&nbsp;', $level * 4) . $value[$this->primary_name];
                    unset($arr[$key]);

                    if ($value['has_children'] == 0) {
                        continue;
                    }
                    $last_cat_id               = $cat_id;
                    $cat_id_array              = array($cat_id);
                    $level_array[$last_cat_id] = ++$level;
                    continue;
                }

                if ($value['parent_id'] == $last_cat_id) {
                    $options[$cat_id]             = $value;
                    $options[$cat_id]['level']    = $level;
                    $options[$cat_id]['opt_name'] = str_repeat('&nbsp;', $level * 4) . $value[$this->primary_name];
                    unset($arr[$key]);

                    if ($value['has_children'] > 0) {
                        if (end($cat_id_array) != $last_cat_id) {
                            $cat_id_array[] = $last_cat_id;
                        }
                        $last_cat_id               = $cat_id;
                        $cat_id_array[]            = $cat_id;
                        $level_array[$last_cat_id] = ++$level;
                    }
                } elseif ($value['parent_id'] > $last_cat_id) {
                    break;
                }
            }

            $count = count($cat_id_array);
            if ($count > 1) {
                $last_cat_id = array_pop($cat_id_array);
            } elseif ($count == 1) {
                if ($last_cat_id != end($cat_id_array)) {
                    $last_cat_id = end($cat_id_array);
                } else {
                    $level        = 0;
                    $last_cat_id  = 0;
                    $cat_id_array = array();
                    continue;
                }
            }

            if ($last_cat_id && isset($level_array[$last_cat_id])) {
                $level = $level_array[$last_cat_id];
            } else {
                $level = 0;
            }
        }
        return $options;
    }

    function priv_name($action_list)
    {
        $priv_name = '';
        if (empty($action_list)) {
            $priv_name = '无权限';
        } else if ($action_list == 'all') {
            $priv_name = '所有权限';
        } else {
            $priv_name = '部分权限：' . count(explode(',', $action_list));
        }
        return $priv_name;
    }


    /**
     * 连接reids
     */
    public function redis_connect()
    {
        $this->config->load('redis', TRUE);

        $redis_config = $this->config->item($this->redis_config, 'redis');
        $host         = $redis_config['host'];
        $password     = $redis_config['password'];
        $port         = $redis_config['port'];
        $timeout      = $redis_config['timeout'];

//		$ttl = $redis_config['ttl'];
        try {
            if ($this->my_redis) return;

            $this->my_redis = new Redis();
            $this->my_redis->connect($host, $port, $timeout, NULL);
            $this->my_redis->auth($password);
        } catch (Exception $e) {
            make_json_error('【redis错误】' . $e->getMessage());
        }
    }

    /*public function ()
    {

    }*/

    //直接返回redis对象，提供给外界使用
    public function redis_obj()
    {
        $this->redis_connect();
        return $this->my_redis;
    }

    /*
     * redis 添加hmset数据
     */
    public function redis_hmset($key, $data = array(), $selected = 0)
    {
        $this->result['error'] = 0;
        if (empty($key)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'key不能为空';
        }
        if ($this->result['error'] == 0) {
            $this->redis_connect();
            if (!$this->my_redis) {
                $this->result['error']   = 1;
                $this->result['message'] = '连接redis错误';
            }

            if ($this->result['error'] == 0) {
                if (!$this->my_redis->hMset($key, $data)) {
                    $this->result['error']   = 1;
                    $this->result['message'] = '数据异常';
                }
            }
            $this->redis_close();
        }
        return $this->result;
    }

    /**
     * @param $key
     * @param $field
     * @param $val
     * @return array
     */
    public function redis_hincrbyfloat($key, $field, $val)
    {
        $this->result['error'] = 0;
        if (empty($key)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'key不能为空';
        }
        if (empty($field)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'field不能为空';
        }
        if ($this->result['error'] == 0) {
            $this->redis_connect();
            if (!$this->my_redis) {
                $this->result['error']   = 1;
                $this->result['message'] = '连接redis错误';
            }

            if ($this->result['error'] == 0) {
                if (false === $this->my_redis->HINCRBYFLOAT($key, $field, $val)) {
                    $this->result['error']   = 1;
                    $this->result['message'] = '数据异常';
                }
            }
            $this->redis_close();
        }
        return $this->result;
    }

    /**
     * 添加集合类型
     * redis_sAdd('name', 21);
     * redis_sAdd('name', array(12,32,43));
     * @param $key
     * @param $val
     * @return array
     */
    public function redis_sAdd($key, $val, $selected = 0)
    {
        $this->result['error'] = 0;
        if (empty($key)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'key不能为空';
        }
        if ($this->result['error'] == 0) {
            $this->redis_connect();
            if (!$this->my_redis) {
                $this->result['error']   = 1;
                $this->result['message'] = '连接redis错误';
            }
            if ($this->result['error'] == 0) {

                $this->my_redis->select($selected);    //选择数据库
                //如果是数组
                if (is_array($val)) {
                    foreach ($val as $k => $v) {
                        $this->my_redis->sAdd($key, $v);
                    }
                } else {
                    $this->my_redis->sAdd($key, $val);
                }
            }
            $this->redis_close();
        }
        return $this->result;
    }

    /**
     * 删除集合中的元素
     * @param $key
     * @param $val
     * @return array
     */
    public function redis_sRem($key, $val)
    {
        $this->result['error'] = 0;
        if (empty($key)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'key不能为空';
        }
        if ($this->result['error'] == 0) {
            $this->redis_connect();
            if (!$this->my_redis) {
                $this->result['error']   = 1;
                $this->result['message'] = '连接redis错误';
            }
            if ($this->result['error'] == 0) {

                //如果是数组
                if (is_array($val)) {
                    foreach ($val as $k => $v) {
                        $this->my_redis->sRem($key, $v);
                    }
                } else {
                    $this->my_redis->sRem($key, $val);
                }
            }
            $this->redis_close();
        }

        return $this->result;
    }


    /**
     *
     * @param array $items
     */
    public function redis_delete($items = array())
    {
        $this->result['error'] = 0;
        if (empty($items)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'key不能为空';
        }
        if ($this->result['error'] == 0) {
            $this->redis_connect();
            if (!$this->my_redis) {
                $this->result['error']   = 1;
                $this->result['message'] = '连接redis错误';
            }
            if ($this->result['error'] == 0) {
                if (false === $this->my_redis->delete($items)) {
                    $this->result['error']   = 1;
                    $this->result['message'] = '数据异常';
                }
            }
            $this->redis_close();
        }
        return $this->result;
    }

    /*
     * redis 添加hset数据
     * $key
     * $field
     * $value
     * $redis->hSet('h', 'key1', 'hello');
     */
    public function redis_hset($key, $field, $value)
    {
        $this->result['error'] = 0;
        if (empty($key)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'key不能为空';
        }
        if (empty($field)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'field不能为空';
        }

        if ($this->result['error'] == 0) {
            $this->redis_connect();
            if (!$this->my_redis) {
                $this->result['error']   = 1;
                $this->result['message'] = '连接redis错误';
            }

            if ($this->result['error'] == 0) {
                if (!$this->my_redis->hSet($key, $field, $value)) {
                    $this->result['error']   = 1;
                    $this->result['message'] = '数据异常';
                }
            }
            $this->redis_close();
//			var_dump($this->my_redis);
        }
        return $this->result;
    }


    /**
     * redis 判断一个键是否存在
     */
    public function redis_exists($key)
    {
        $this->result['error'] = 0;
        if (empty($key)) {
            $this->result['error']   = 1;
            $this->result['message'] = 'key不能为空';
        }
        if ($this->result['error'] == 0) {
            $this->redis_connect();
            if (!$this->my_redis) {
                $this->result['error']   = 1;
                $this->result['message'] = '连接redis错误';
            }
            if ($this->result['error'] == 0) {
                $this->result['exists'] = $this->my_redis->exists($key);
            }
            $this->redis_close();
        }
        return $this->result;
    }

    /**
     * redis 事务锁
     * @return [type] [description]
     */
    public function redis_lock($key, $expire = 10)
    {
        if (!$key) {
            $this->result['error']   = 1;
            $this->result['message'] = 'keys不能为空';
            return $this->result;
        }

        $this->redis_connect();
        if (!$this->my_redis) {
            $this->result['error']   = 1;
            $this->result['message'] = '连接redis错误';
            return $this->result;
        }
        $redis = $this->my_redis;
        do {
            if ($acquired = ($redis->setnx("Lock:{$key}", time()))) { // 如果redis不存在，则成功
                $redis->expire("Lock:{$key}", $expire);
                break;
            }

        } while (true);

        return true;
    }

    /**
     * 释放锁
     * @param  [type] $key [description]
     * @return [type]      [description]
     */
    public function redis_release($key)
    {
        $res = $this->redis_delete(array("Lock:{$key}"));
    }

    /**
     * 断开reids
     */
    public function redis_close()
    {
//        $this->my_redis->close();
    }


}

?>